

//标识当前是使用了微任务还是宏任务来执行任务队列标识
export let isUsingMicroTask = false

const callbacks = []
let pending = false

function flushCallbacks () {
  pending = false
  const copies = callbacks.slice(0)
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    copies[i]()
  }
}

let timerFunc

//条条大路通罗马，选择一条路最好的，代步工具最舒服的去罗马
if (typeof Promise !== 'undefined') {
  const p = Promise.resolve()
  timerFunc = () => {
    p.then(flushCallbacks)
  }
  isUsingMicroTask = true
} else if (typeof MutationObserver !== 'undefined' && (
  MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
  let counter = 1
  const observer = new MutationObserver(flushCallbacks)
  const textNode = document.createTextNode(String(counter))
  observer.observe(textNode, {
    characterData: true
  })
  timerFunc = () => {
    counter = (counter + 1) % 2
    textNode.data = String(counter)
  }
  isUsingMicroTask = true
} else if (typeof setImmediate !== 'undefined' ) {
  timerFunc = () => {
    setImmediate(flushCallbacks)
  }
} else {
  timerFunc = () => {
    setTimeout(flushCallbacks, 0)
  }
}

export function nextTick (cb, ctx) {
  let _resolve
  callbacks.push(() => {
    if (cb) {
      try {
        cb.call(ctx)
      } catch (e) {
        console.error('表达式函数出错：', e);
      }
    } else if (_resolve) {
      _resolve(ctx)
    }
  })
  //锁定开关，当前同步任务运行完成，开始进入循环队列
  //此时执行循环队列里面的任务如果又有使用了nextTick方法的
  //任务产生，不再开始异步队列，而是直接将任务传递进callbacks数组里面
  //排队执行
  if (!pending) {
    pending = true
    timerFunc()
  }
  
  //没有传递cb执行函数，采用了Promise回调方式
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve
    })
  }
}
